package com.corticon.dialogs.designer.licence;

import static org.apache.commons.codec.binary.Base64.encodeBase64;
import static org.apache.commons.codec.binary.Base64.decodeBase64;

import java.security.*;
import java.security.spec.X509EncodedKeySpec;

/**
 * It is encryptor to generate and verify the signature on data.
 * User: wupeng
 * Date: 2010-3-9
 * Time: 11:44:01
 * To change this template use File | Settings | File Templates.
 */
public class Coder {
    private static String SIGNTURE_ALGORITHM = "DSA";
    private static String KEY_ALGORITHM = "DSA";

    /**
     * Generate the signature with private key
     * 
     * @param data A byte[] containing the data to be signed.
     * @param privateKey
     * @return a encoded signature string with Base64
     * @throws Exception
     */
    public static String sign(byte[] data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNTURE_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data);
        return bytesToString(encodeBase64(signature.sign()));
    }

    /**
     *
     * @param data A byte[] containing the data to be verified.
     * @param publicKeyBase64X509 A string encoded with Base64 and X509 spec.
     * @param signBase64 A encoded signature string with Base64.
     * @return A boolean if the data is verified
     * @throws Exception
     */
    public static boolean verify(byte[] data, String publicKeyBase64X509, String signBase64) throws Exception {
        // decode the publicKey with Base64
        byte[] publicKeyX509Bytes = decodeBase64(publicKeyBase64X509.getBytes());

        // Construct the X509EncodedKeySpec object.
        X509EncodedKeySpec publicKeyX509Spec = new X509EncodedKeySpec(publicKeyX509Bytes);

        // Get public key with specified algorithm.
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(publicKeyX509Spec);

        Signature signature = Signature.getInstance(SIGNTURE_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data);

        return signature.verify(decodeBase64(signBase64.getBytes()));
    }

    /**
     * Generate the Key pair
     * @return KeyPair object
     * @throws Exception
     */
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
         keyPairGen.initialize(1024);  
         return keyPairGen.generateKeyPair();
    }

    /**
     * Get private key
     * @param keyPair
     * @return
     */
    public static PrivateKey getPivateKey(KeyPair keyPair) {
        return keyPair.getPrivate();
    }

    /**
     * Get public key
     * @param keyPair
     * @return
     */
    public static PublicKey getPublicKey(KeyPair keyPair) {
        return keyPair.getPublic();
    }

    /**
     * Convert bytes to string.
     * @param encrytpByte
     * @return
     */
    public static String bytesToString(byte[] encrytpByte) {
        String result = "";
        for (Byte bytes : encrytpByte) {
            result += (char) bytes.intValue();
        }
        return result;
    }

}
